///\todo upgrade

//////////////////////////////////////////////////////////////////////////////////
//                                                                              //
//  This file is part of the buola project (https://code.google.com/p/buola/).  //
//                                                                              //
//  Copyright(c) 2007-2012 Xavi Gratal                                          //
//  gratal AT gmail DOT com                                                     //
//                                                                              //
//  Buola is free software: you can redistribute it and/or modify               //
//  it under the terms of the GNU General Public License as published by        //
//  the Free Software Foundation, either version 3 of the License, or           //
//  (at your option) any later version.                                         //
//                                                                              //
//  Buola is distributed in the hope that it will be useful,                    //
//  but WITHOUT ANY WARRANTY; without even the implied warranty of              //
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               //
//  GNU General Public License for more details.                                //
//                                                                              //
//  You should have received a copy of the GNU General Public License           //
//  along with buola.  If not, see <http://www.gnu.org/licenses/>.              //
//                                                                              //
//////////////////////////////////////////////////////////////////////////////////

#ifndef _IO_H_BUOLA_IMAGE_
#define _IO_H_BUOLA_IMAGE_

#include <buola/image.h>
#include <buola/image/cimageplugin.h>
#include <buola/image/ccodec.h>
#include <buola/image/canyimage.h>
#include <buola/io/cfile.h>

#include <buola/io/curi.h>
#include <buola/io/cfixedmemstream.h>

namespace buola { namespace img {

inline void load(CAnyImage &pImg,const io::CURI &pURI,EImageFormat pFormat=FORMAT_ANY,const CSize_i &pSize=nUndefined)
{
    CCodec *lCodec=CImagePlugin::GetCodec(pURI.Extension());

    if(!lCodec) throw XNotFound(I18N("can't find codec for ")+pURI.Extension());

    io::PBufferStream lStream=io::CFile(pURI).GetBufferStream(io::EMode::READ);

    lCodec->Read(lStream,pImg,pFormat,pSize);

    if(pFormat!=FORMAT_ANY&&pImg.Format()!=pFormat)
        pImg.Convert(pFormat);

    delete lCodec;
}

inline CAnyImage load(const io::CURI &pURI,EImageFormat pFormat=FORMAT_ANY,const CSize_i &pSize=nUndefined)
{
    CAnyImage lImg;
    load(lImg,pURI,pFormat,pSize);
    return lImg;
}

template<typename tFormat>
inline void load(CImage<tFormat> &pImg,const io::CURI &pURI,const CSize_i &pSize=CSize_i(nUndefined))
{
    pImg=CImage<tFormat>(load(pURI,tFormat::mID,pSize));
}

template<typename tImg>
inline tImg load(const io::CURI &pURI,const CSize_i &pSize=CSize_i(nUndefined))
{
    return tImg(load(pURI,tImg::TFormat::mID,pSize));
}

inline void load_mem(CAnyImage &pImg,const uint8_t *pBuffer,int pLength,const std::string &pCodec,EImageFormat pFormat=FORMAT_ANY,
                   const CSize_i &pSize=nUndefined)
{
    CCodec *lCodec=CImagePlugin::GetCodec(pCodec);

    if(!lCodec) throw XNotFound(I18N("can't find codec ")+pCodec);

    io::PFixedMemStream lStream=new io::CFixedMemStream(pBuffer,pBuffer+pLength);
    lCodec->Read(lStream,pImg,pFormat,pSize);

    if(pFormat!=FORMAT_ANY&&pImg.Format()!=pFormat)
        pImg.Convert(pFormat);

    delete lCodec;
}

inline CAnyImage load_mem(const uint8_t *pBuffer,size_t pLength,const std::string &pCodec,EImageFormat pFormat=FORMAT_ANY)
{
    CAnyImage lImg;
    load_mem(lImg,pBuffer,pLength,pCodec,pFormat);
    return lImg;
}

template<typename tImg> inline tImg load_mem(const uint8_t *pBuffer,size_t pLength,const std::string &pCodec)
{
    return tImg(load_mem(pBuffer,pLength,pCodec,tImg::TFormat::mID));
}

inline void save(const img::CAnyView &pView,const io::CURI &pURI)
{
    CCodec *lCodec=CImagePlugin::GetCodec(pURI.Extension());

    if(!lCodec) throw XNotFound(I18N("can't find codec"));

    io::PBufferStream lStream=io::CFile(pURI).GetBufferStream(io::EMode::TRUNCATE);
    lCodec->Write(pView,lStream);

    delete lCodec;
}

template<typename tFormat>
inline void load_raw(CImage<tFormat> &pImg,const io::CURI &pURI,const CSize_i &pSize)
{
    pImg.Recreate(pSize);
    io::PStream lStream=io::open(pURI,io::EMode::READ);
    lStream->Read(pImg.RawBytes(),pSize.x*pSize.y*tFormat::mPixelSize);
}

void load_rgbd(CImage_rgb8 &pRGB,CImage_gray32f &pDepth,const io::CURI &pURI);

template<typename tFormat>
inline void load_ascii(CImage<tFormat> &pImg,const io::CURI &pURI,const CSize_i &pSize)
{
    pImg.Recreate(pSize);
    io::CTextReader lStream(pURI);
    for(int y=0;y<pSize.y;y++)
    {
        for(int x=0;x<pSize.x;x++)
        {
            for(int c=0;c<tFormat::TColorSpace::cChannels;c++)
            {
                lStream >> pImg(x,y)[c];
            }
        }
    }
}

/*namespace img*/ } /*namespace buola*/ }

#endif
